#Code for the models behind the table views
#Data comes from GUI Controller and Qt calls
#data() internally to update the list.

3
#Written by Nathan

from PyQt4 import QtCore as QC

invindex = QC.QModelIndex()

class DynamicTableModel(QC.QAbstractTableModel):
    def __init__(self, in_dataLabels, in_qparent=None):
        """Constructor takes a list of prefixes you want on each column,
        stores it, and initializes an empty list of rows.
        """
        QC.QAbstractTableModel.__init__(self, in_qparent)
        self.prefixes = in_dataLabels
        self.rows = []
               
    def rowCount(self, in_qparent):
        """QT table spec: If parent valid return 0.
        Otherwise return number of rows. Used internally by PyQt, avoid
        writing methods which call this.
        """
        if in_qparent.isValid(): return 0
        return len(self.rows)
    
    def columnCount(self, in_qparent):
        """QT table spec: If parent valid return 0.
        Otherwise return number of columns. Used internally by PyQt, avoid
        writing methods which call this.
        """
        if in_qparent.isValid(): return 0
        return len(self.prefixes)
    
    def data(self, in_qindex, in_qrole):
        """Used internally by PyQt, avoid writing methods which call this.
        """
        ret = None
        if in_qrole == QC.Qt.DisplayRole and in_qindex.isValid():
            ret = str(self.rows[in_qindex.row()][in_qindex.column()])
        return ret

    def headerData(self, in_col, in_qorient, in_qrole):
        """Used internally by PyQt, avoid writing methods which call this.
        """
        ret = None
        if in_qorient == QC.Qt.Horizontal and in_qrole == QC.Qt.DisplayRole:
            ret = self.prefixes[in_col]
        return ret
            
    def sort(self, in_col, in_qorder):
        """Used internally by PyQt, avoid writing methods which call this.
        """
        self.emit(QC.SIGNAL("layoutAboutToBeChanged()"))
        self.rows = sorted(self.rows, key=lambda x: x[in_col])
        if in_qorder == QC.Qt.DescendingOrder:
            self.rows.reverse()
        self.emit(QC.SIGNAL("layoutChanged()"))
        
    def insert_row(self, in_data):
        """Use update_rows() for changing table's data structure.
        """
        end = len(self.rows)
        self.beginInsertRows(invindex, end, end)
        self.rows.append(in_data)
        self.endInsertRows()
        
    def remove_row(self, in_name):
        """Use update_rows() for changing table's data structure.
        """
        names = map(lambda x: x[0], self.rows)
        try: row = names.index(in_name)
        except Exception: row = -1

        if row > -1:                
            self.beginRemoveRows(invindex, row, row)
            del self.rows[row]
            self.endRemoveRows()

    def update_rows(self, in_names):
        """Takes a list of torrent names which you wish to track.
        Removes obsolete names, and puts rows of zeroes for new names. 
        """
        #pulls all of the names from the nested lists in rows
        #and puts them in names
        names = map(lambda x: x[0], self.rows)
        
        old = set(names)
        new = set(in_names)
        
        for name in (old-new):
            self.remove_row(name)
        
        for name in (new-old):
            row = [0]*len(self.prefixes)
            row[0] = name
            self.insert_row(row)
        
    def refresh_row(self, in_data):
        """Takes an updated row for an already inserted torrent.
        Replaces the old row with the new row, and signals a change
        in the data for Qt to re-draw.
        """
        names = map(lambda x: x[0], self.rows)
        try: row = names.index(in_data[0])
        except Exception: row = -1
        
        if row > -1:
            self.rows[row] = in_data
            l_qindex = self.index(row, 1, invindex)
            r_qindex = self.index(row, len(self.prefixes), invindex)
            self.emit(QC.SIGNAL("dataChanged(const QModelIndex &, const QModelIndex &)"), l_qindex, r_qindex)
            